package com.ruoyi.workflow.service.impl;


import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.ruoyi.common.core.domain.entity.SysDept;
import com.ruoyi.common.core.domain.entity.SysRole;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.helper.LoginHelper;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.flowable.common.constant.ProcessConstants;
import com.ruoyi.flowable.common.constant.TaskConstants;
import com.ruoyi.flowable.common.enums.FlowComment;
import com.ruoyi.flowable.factory.FlowServiceFactory;
import com.ruoyi.flowable.flow.CustomProcessDiagramGenerator;
import com.ruoyi.flowable.flow.FindNextNodeUtil;
import com.ruoyi.flowable.flow.FlowableUtils;
import com.ruoyi.flowable.utils.ModelUtils;
import com.ruoyi.flowable.utils.TaskUtils;
import com.ruoyi.system.domain.SysPost;
import com.ruoyi.system.domain.SysUserPost;
import com.ruoyi.system.mapper.*;
import com.ruoyi.system.service.ISysRoleService;
import com.ruoyi.system.service.ISysUserService;
import com.ruoyi.workflow.domain.bo.WfTaskBo;
import com.ruoyi.workflow.domain.dto.WfNextDto;
import com.ruoyi.workflow.domain.vo.WfViewerVo;
import com.ruoyi.workflow.mapper.WfDefComponentMapper;
import com.ruoyi.workflow.service.ISysService;
import com.ruoyi.workflow.service.IWfCopyService;
import com.ruoyi.workflow.service.IWfTaskService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.flowable.bpmn.constants.BpmnXMLConstants;
import org.flowable.bpmn.model.Process;
import org.flowable.bpmn.model.*;
import org.flowable.common.engine.api.FlowableException;
import org.flowable.common.engine.api.FlowableObjectNotFoundException;
import org.flowable.common.engine.impl.identity.Authentication;
import org.flowable.engine.ProcessEngineConfiguration;
import org.flowable.engine.history.HistoricActivityInstance;
import org.flowable.engine.history.HistoricActivityInstanceQuery;
import org.flowable.engine.history.HistoricProcessInstance;
import org.flowable.engine.repository.ProcessDefinition;
import org.flowable.engine.runtime.Execution;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.image.ProcessDiagramGenerator;
import org.flowable.task.api.DelegationState;
import org.flowable.task.api.Task;
import org.flowable.task.api.history.HistoricTaskInstance;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.client.RestTemplate;

import java.io.InputStream;
import java.time.Duration;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;


@RequiredArgsConstructor
@Service
@Slf4j
public class SysServiceImpl extends FlowServiceFactory implements ISysService {

    private final SysUserMapper userMapper;
    private final SysDeptMapper deptMapper;
    private final SysRoleMapper roleMapper;
    private final SysPostMapper postMapper;

    private final SysUserRoleMapper userRoleMapper;
    private final SysUserPostMapper userPostMapper;

    private static final String KEZHANG = "课长";

    private static final String SHANGNJI = "上一级";

    private static final String SHANGNSHANGJI = "上两级";

    private static final String SHANGNSANJI = "上三级";

    private static final String ZONGJINGLI = "总经理";

    private static final String RENSHIBUJINGLI = "行政";

    private static final String JINGLI = "经理";

    private static final String FUJING = "副经";

    private static final String XIELI = "协理";
    private static final String BAOAN = "保安";

    private static final String RENSHIZHUANYUAN = "人事专员";
    private static final String KAOQINZHUANYUAN = "考勤专员";

    private String parseUserIdByTaskAndUserid(Task task,String userId){
        SysUser sysUser = userMapper.selectVoOne(new LambdaQueryWrapper<SysUser>().eq(SysUser::getUserId,userId));
        if(ObjectUtil.isEmpty(sysUser.getSupDeptCode())){
            return null;
        }
        SysPost post = postMapper.selectVoOne(new LambdaQueryWrapper<SysPost>().eq(SysPost::getPostCode, sysUser.getSupDeptCode()));
        List<SysUserPost> sysUserPosts = userPostMapper.selectVoList(new LambdaQueryWrapper<SysUserPost>().eq(SysUserPost::getPostId,post.getPostId()));
        for(SysUserPost userPost : sysUserPosts){
            SysPost sysPost = postMapper.selectVoById(userPost.getPostId());
            List<SysUser> sysUsers = userMapper.selectList(new LambdaQueryWrapper<SysUser>().eq(SysUser::getUserId, userPost.getUserId()));
            for(SysUser item : sysUsers){
                if(ObjectUtil.isNotNull(sysPost)&&this.checkTaskNameEqualsePostName(task.getName(),sysPost.getPostName())){
                    return sysPost.getPostName();
                }else{
                    return this.parseUserIdByTaskAndUserid(task,item.getUserId().toString());
                }
            }
        }
        return null;
    }
    private boolean checkTaskNameEqualsePostName(String postName,String taskName){
        return
            postName.contains(KEZHANG)&&taskName.contains(KEZHANG)||
                postName.contains(ZONGJINGLI)&&taskName.contains(ZONGJINGLI)||
                postName.contains(RENSHIBUJINGLI)&&taskName.contains(RENSHIBUJINGLI)||
                postName.contains("-"+JINGLI)&&taskName.contains(JINGLI)||
                postName.contains(FUJING)&&taskName.contains(FUJING)||
                postName.contains(XIELI)&&taskName.contains(XIELI)||
                postName.contains(BAOAN)&&taskName.contains(BAOAN)||
                postName.contains("-"+RENSHIZHUANYUAN)&&taskName.contains(RENSHIZHUANYUAN)||
                postName.contains(KAOQINZHUANYUAN)&&taskName.contains(KAOQINZHUANYUAN);
    }

    private String parsePostNameByUserId(String userId){
        SysUser sysUser = userMapper.selectVoOne(new LambdaQueryWrapper<SysUser>().eq(SysUser::getUserId,userId));
        List<SysUserPost> sysUserPosts = userPostMapper.selectVoList(new LambdaQueryWrapper<SysUserPost>().eq(SysUserPost::getPostId,sysUser.getSupDeptCode()));
        SysPost sysPost = postMapper.selectVoById(sysUserPosts.get(0).getPostId());
        return sysPost.getPostName();
    }

    public void setCandidateUsers(Task task,String userId){

        if(ObjectUtil.isNull(task)|| ObjectUtil.isNull(task.getName())){
        }
        else if(task.getName().contains(SHANGNJI)){
            this.setCandidateByShangJi(task,userId);
        }
        else if(task.getName().contains(SHANGNSHANGJI)){
            this.setCandidateByShangShangJi(task,userId);
        }
        else if(task.getName().contains(SHANGNSANJI)){
            this.setCandidateByShangShangShangJi(task,userId);
        }
        else if(task.getName().contains("总经理")){
            this.setCandidateByZongJingLi(task);
        }
        else if(task.getName().contains("行政人事部经理")){
            this.setCandidateByRenShiXingzhengJingli(task);
        }
        else if(task.getName().contains("协理")){
            this.setCandidateByXieLi(task);
        }
        else if(task.getName().contains("保安")){
            this.setCandidateByBaoAn(task);
        }
        else if(task.getName().contains("人事专员")||task.getName().contains("考勤专员")){
            this.setCandidateByRenShiZhuanyuan(task);
        }
        taskService.addCandidateUser(task.getId(),userMapper.selectUserByUserName(PERM).getUserId().toString());
    }

    private static final String PERM = "admin";
    public SysPost getPostUserId(String userId){
        SysUser sysUser = userMapper.selectUserById(Long.parseLong(userId));
        List<SysUserPost> sysUserPosts = userPostMapper.selectVoList(new LambdaQueryWrapper<SysUserPost>().eq(SysUserPost::getUserId,userId));
        if(ObjectUtil.isEmpty(sysUserPosts))throw new ServiceException(sysUser.getNickName()+"员工没有职位");
        SysPost sysPost = postMapper.selectVoById(sysUserPosts.get(0).getPostId());
        if(ObjectUtil.isEmpty(sysPost))throw new ServiceException(sysUserPosts.get(0).getPostId()+"职位ID不存在");
        return sysPost;
    }
    public SysPost getShangJiPostByUserId(String userId){
        SysUser sysUser = userMapper.selectUserById(Long.parseLong(userId));
        SysPost sysPost = postMapper.selectVoOne(new LambdaQueryWrapper<SysPost>().eq(SysPost::getPostCode, sysUser.getSupDeptCode()));
        if(ObjectUtil.isEmpty(sysPost))throw new ServiceException(sysUser.getNickName()+"员工上级职位不能为空");
        return sysPost;
    }
    public SysPost getShangShangJiPostByUserId(String userId){
        SysUser sysUser = this.getShangJiUserByUserId(userId);
        SysPost sysPost = this.getShangJiPostByUserId(sysUser.getUserId() + "");
        return sysPost;
    }
    public SysPost getShangShangShangJiPostByUserId(String userId){
        SysUser sysUser = this.getShangJiUserByUserId(userId);
        sysUser = this.getShangJiUserByUserId(sysUser.getUserId() + "");
        SysPost sysPost = this.getShangJiPostByUserId(sysUser.getUserId() + "");
        return sysPost;
    }
    public SysUser getShangJiUserByUserId(String userId){
        SysPost sysPost= this.getShangJiPostByUserId(userId);
        List<SysUserPost> sysUserPosts = userPostMapper.selectVoList(new LambdaQueryWrapper<SysUserPost>().eq(SysUserPost::getPostId,sysPost.getPostId()));
        if(ObjectUtil.isEmpty(sysUserPosts))throw new ServiceException(sysPost.getPostId()+"上级员工不能为空");
        SysUser sysUser = userMapper.selectUserById(sysUserPosts.get(0).getUserId());
        return sysUser;
    }

    public SysUser getShangShangJiUserByUserId(String userId){
        SysPost sysPost= this.getShangShangJiPostByUserId(userId);
        List<SysUserPost> sysUserPosts = userPostMapper.selectVoList(new LambdaQueryWrapper<SysUserPost>().eq(SysUserPost::getPostId,sysPost.getPostId()));
        if(ObjectUtil.isEmpty(sysUserPosts))throw new ServiceException(sysPost.getPostId()+"员工上上级职位不能为空");
        SysUser sysUser = userMapper.selectUserById(sysUserPosts.get(0).getUserId());
        return sysUser;
    }
    public SysUser getShangShangShangJiUserByUserId(String userId){
        SysPost sysPost= this.getShangShangShangJiPostByUserId(userId);
        List<SysUserPost> sysUserPosts = userPostMapper.selectVoList(new LambdaQueryWrapper<SysUserPost>().eq(SysUserPost::getPostId,sysPost.getPostId()));
        if(ObjectUtil.isEmpty(sysUserPosts))throw new ServiceException(sysPost.getPostId()+"员工上上上级职位不能为空");
        SysUser sysUser = userMapper.selectUserById(sysUserPosts.get(0).getUserId());
        return sysUser;
    }

    public void setCandidateByShangJi(Task task,String userId){
        taskService.addCandidateUser(task.getId(),this.getShangJiUserByUserId(userId).getUserId() +"");
    }
    public void setCandidateByShangShangJi(Task task,String userId){
        taskService.addCandidateUser(task.getId(),this.getShangShangJiUserByUserId(userId).getUserId() +"");
    }
    public void setCandidateByShangShangShangJi(Task task,String userId){
        taskService.addCandidateUser(task.getId(),this.getShangShangShangJiUserByUserId(userId).getUserId() +"");
    }
    /**
     * 所有经理都可以审批
     * @return
     */
    public void setCandidateByJingLi(Task task,String userId){
        SysUser sysUser = userMapper.selectVoOne(new LambdaQueryWrapper<SysUser>().eq(SysUser::getUserId,userId));
        Long deptId = sysUser.getDeptId();
        List<SysUser> sysUsers = userMapper.selectList(new LambdaQueryWrapper<SysUser>().eq(SysUser::getDeptId, deptId));
        for(SysUser user : sysUsers){
            List<SysUserPost> sysUserPosts = userPostMapper.selectList(new LambdaQueryWrapper<SysUserPost>().eq(SysUserPost::getUserId, user.getUserId()));
            for(SysUserPost userPost : sysUserPosts){
                SysPost sysPost = postMapper.selectVoById(userPost.getPostId());
                if(ObjectUtil.isNotNull(sysPost)&&(sysPost.getPostName().contains("经理")||sysPost.getPostName().contains("副理"))){
                    taskService.addCandidateUser(task.getId(),user.getUserId().toString());
                    break;
                }
            }
        }
    }
    /**
     * 总经理审批
     * @return
     */
    public void setCandidateByZongJingLi(Task task){
        List<SysPost> sysPosts = postMapper.selectList(new LambdaQueryWrapper<SysPost>().like(SysPost::getPostName, "%总经理%"));
        for(SysPost sysPost : sysPosts){
            List<SysUserPost> sysUserPosts = userPostMapper.selectList(new LambdaQueryWrapper<SysUserPost>().eq(SysUserPost::getPostId, sysPost.getPostId()));
            for (SysUserPost sysUserPost:sysUserPosts){
                SysUser sysUser = userMapper.selectById(sysUserPost.getUserId());
                if(ObjectUtil.isNotNull(sysUser)) {
                    taskService.addCandidateUser(task.getId(),sysUser.getUserId().toString());
                }
            };
        }
    }

    /**
     *协理
     *
     * @return
     */
    public void setCandidateByXieLi(Task task){
        List<SysPost> sysPosts = postMapper.selectList(new LambdaQueryWrapper<SysPost>().like(SysPost::getPostName, "%协理%"));
        for(SysPost sysPost : sysPosts){
            List<SysUserPost> sysUserPosts = userPostMapper.selectList(new LambdaQueryWrapper<SysUserPost>().eq(SysUserPost::getPostId, sysPost.getPostId()));
            for (SysUserPost sysUserPost:sysUserPosts){
                taskService.addCandidateUser(task.getId(),sysUserPost.getUserId().toString());
            };
        }
    }

    /**
     * 行政人事部经理
     *
     * @return
     */
    public void setCandidateByRenShiXingzhengJingli(Task task){
        List<SysPost> sysPosts = postMapper.selectList(new LambdaQueryWrapper<SysPost>().like(SysPost::getPostName, "%行政人事部经理%"));
        for(SysPost sysPost : sysPosts){
            List<SysUserPost> sysUserPosts = userPostMapper.selectList(new LambdaQueryWrapper<SysUserPost>().eq(SysUserPost::getPostId, sysPost.getPostId()));
            for (SysUserPost sysUserPost:sysUserPosts){
                taskService.addCandidateUser(task.getId(),sysUserPost.getUserId().toString());
            };
        }
    }
    /**
     * 保安
     *
     * @return
     */
    public void setCandidateByBaoAn(Task task){
        List<SysDept> sysDepts = deptMapper.selectDeptList(new LambdaQueryWrapper<SysDept>().like(SysDept::getDeptName, "保安"));
        for(SysDept sysDept:sysDepts){
            List<SysUser> sysUsers = userMapper.selectUserList(new LambdaQueryWrapper<SysUser>().eq(SysUser::getDeptId, sysDept.getDeptId()));
            for(SysUser sysUser:sysUsers){
                taskService.addCandidateUser(task.getId(),sysUser.getUserId().toString());
            }
        }
    }
    /**
     * 人事专员
     *
     * @return
     */
    public void setCandidateByRenShiZhuanyuan(Task task){
        List<SysPost> sysPosts = postMapper.selectList(new LambdaQueryWrapper<SysPost>().like(SysPost::getPostName, "-人事专员"));
        for(SysPost sysPost:sysPosts){
            List<SysUserPost> sysUserPosts = userPostMapper.selectList(new LambdaQueryWrapper<SysUserPost>().eq(SysUserPost::getPostId, sysPost.getPostId()));
            for(SysUserPost sysUserPost:sysUserPosts){
                taskService.addCandidateUser(task.getId(),sysUserPost.getUserId().toString());
            }
        }
    }

    @Override
    public SysDept selectDeptById(Long id) {
        return deptMapper.selectVoById(id);
    }

    @Override
    public SysUser selectUserById(Long id) {
        return userMapper.selectUserById(id);
    }

    @Override
    public void setDefaultVariables(Map<String, Object> variables,Long userId) {
        SysUser sysUser = userMapper.selectUserById(userId);
        SysPost sysPost = this.getPostUserId(userId+"");
        variables.put("postName",sysPost.getPostName().substring(sysPost.getPostName().indexOf("--")+ 2));
        variables.put("postCode",sysPost.getPostCode());
        sysPost = this.getShangJiPostByUserId(sysUser.getUserId()+"");
        variables.put("postName1",sysPost.getPostName().substring(sysPost.getPostName().indexOf("--")+ 2));
        variables.put("postCode1",sysPost.getPostCode());
        sysPost = this.getShangShangJiPostByUserId(sysUser.getUserId() + "");
        variables.put("postName2",sysPost.getPostName().substring(sysPost.getPostName().indexOf("--")+ 2));
        variables.put("postCode2",sysPost.getPostCode());
        SysDept sysDept = deptMapper.selectVoById(sysUser.getDeptId());
        variables.put("deptName",sysDept.getDeptName());
        variables.put("deptCode",sysDept.getDeptCode());
        variables.put("dutyCode",sysUser.getDutyCode());
        variables.put("dutyName",sysUser.getDutyName());
    }

}
